package per.destiny.reflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.Random;
import java.util.UUID;

public class RelfectDemo {

    public static void main(String[] args) {
        try {
            Class<Person> clazz = Person.class;
            // newInstance(clazz);
            // printConstruct(clazz);
            // useConstruct(clazz.getConstructors());

            // 获取本类以及父类或者父接口中所有的公共方法
            // useMethod(clazz.getMethods());

            // 获取本类中的所有方法（包括私有，保护，默认以及public）
            // useMethod(clazz.getDeclaredMethods());

            //打印类注解
//            printAnnotation(clazz);
            //使用类注解
//            useSomeAnnotation(clazz);

            //使用属性的注解
                //printFieldAnnotation(clazz);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private static void printFieldAnnotation(Class<Person> clazz) throws InvocationTargetException, IllegalAccessException {
        Field[] fields =  clazz.getDeclaredFields();

        for (Field field :fields) {
            Annotation[] annotations = field.getDeclaredAnnotations();

            for (Annotation annotaion : annotations) {
                Class<? extends  Annotation> annotationClazz = annotaion.annotationType();
                Method[] methods = annotationClazz.getDeclaredMethods();

                for (Method method : methods) {
                    Object object = method.invoke(annotaion);
                    System.err.println(field.getName() + "-" +method.getName() + "-" +object);
                }
            }
        }
    }

    private static void useSomeAnnotation(Class<Person> clazz) throws InvocationTargetException, IllegalAccessException {
        //是否有该注解
        boolean flag = clazz.isAnnotationPresent(Entity.class);
        if(!flag){
            return;
        }
        Annotation entityAnnotation = clazz.getAnnotation(Entity.class);
        Class<? extends Annotation> entityClazz = entityAnnotation.annotationType();

        Method[] methods = entityClazz.getDeclaredMethods();
        for (Method method :methods) {
            Object result = method.invoke(entityAnnotation);
            System.err.println("结果是:"+ result);
        }
    }

    private static void printAnnotation(Class<Person> clazz) throws InvocationTargetException, IllegalAccessException, InstantiationException {
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            Class<? extends Annotation> annotationClass = annotation.annotationType();
            System.err.println(annotationClass.getName());
            Method[] methods = annotationClass.getDeclaredMethods();
            for (Method method:methods) {
                System.err.println("method.getName() = " + method.getName());
                Object object =  method.invoke(annotation);
                System.err.println("注解的值 = " + object);
            }
        }

    }

    private static void useMethod(Method[] methods) throws Exception {
        Person person = new Person("name", 10);
        System.err.println("开始使用方法");
        for (Method method : methods) {

            if (method.getName().startsWith("get")) {
                Object object = method.invoke(person);
                System.err.println("method.getName() = " + method.getName() + ",result = " + object);
            } else if (method.getName().startsWith("set")) {
                Class<?>[] paramTypes = method.getParameterTypes();
                if ("java.lang.String".equals(paramTypes[0])) {
                    Object object = method.invoke(person, UUID.randomUUID().toString());
                    System.err.println("method.getName() = " + method.getName() + ",result = " + object);
                } else if ("java.lang.Integer".equals(paramTypes[0])) {
                    Object object = method.invoke(person, new Random().nextInt(100));
                    System.err.println("method.getName() = " + method.getName() + ",result = " + object);
                }
            } else if ("sing".equals(method.getName())) {
                // 私有方法设置为true，才可以调用，否则会报错：java.lang.IllegalAccessException
                method.setAccessible(true);
                method.invoke(person);
            }
        }
        System.err.println("结束使用方法");
    }

    private static void useConstruct(Constructor<?>[] constructors) throws Exception {
        System.err.println("开始使用构造器");
        for (Constructor<?> constructor : constructors) {
            int paramCount = constructor.getParameterCount();
            if (0 == paramCount) {
                Object object = constructor.newInstance();
                System.err.println("param 0 newInstance is :{}" + object);
            } else {
                Parameter[] parameters = constructor.getParameters();
                Object[] objects = new Object[parameters.length];
                for (int i = 0, length = parameters.length; i < length; i++) {
                    Class<?> typeClass = parameters[i].getType();
                    if ("java.lang.Integer".equals(typeClass.getName())) {
                        objects[i] = new Random().nextInt(100);
                    } else if ("java.lang.String".equals(typeClass.getName())) {
                        objects[i] = UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
                    }

                }
                Object object = constructor.newInstance(objects);
                System.err.println("object = " + object);
            }
        }
        System.err.println("结束使用构造器");
    }

    public static Class<?> getClass1(Object object) {
        Class<?> clazz = object.getClass();
        return clazz;
    }

    public static Class<?> getClass2(String name) {
        Class<?> clazz = null;
        try {
            clazz = Class.forName(name);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return clazz;
    }

    private static void newInstance(Class<?> clazz) throws Exception {
        System.err.println("开始实例化对象");
        Object object = clazz.newInstance();
        System.err.println(object);
        System.err.println("结束实例化对象");
    }

    private static void printConstruct(Class<?> clazz) throws Exception {
        // 获取构造器
        Constructor<?>[] constructors = clazz.getConstructors();
        System.err.println("开始打印构造器");
        for (Constructor<?> constructor : constructors) {
            System.err.println("constructor.getName():" + constructor.getName());
            Parameter[] parameters = constructor.getParameters();
            printParameters(parameters);
            Class<?>[] parameterTypes = constructor.getParameterTypes();
            for (Class<?> paramType : parameterTypes) {
                System.err.print("(");
                System.err.print(paramType.getName());
                System.err.print(")");
            }
            System.err.println();

            System.err.println("constructor.getModifiers():" + constructor.getModifiers());
            System.err.println("constructor.toGenericString():" + constructor.toGenericString());
            System.err.println("constructor.toString():" + constructor.toString());
            System.err.println("----------------------------------");
        }
        System.err.println("结束打印构造器");
    }

    private static void printParameters(Parameter[] parameters) {
        if (null == parameters || parameters.length < 1) {
            return;
        }
        System.err.println("开始打印参数");
        for (Parameter parameter : parameters) {
            System.err.println("parameter.getName() = " + parameter.getName());
        }
        System.err.println("结束打印参数");
    }

}
